//! # 安全错误类型
//!
//! 统一的安全相关错误类型定义，在整个 RustCloud 生态系统中使用。

use thiserror::Error;

/// 认证错误类型
#[derive(Error, Debug, Clone, PartialEq)]
pub enum AuthError {
    #[error("认证失败: {0}")]
    AuthenticationFailed(String),
    
    #[error("授权失败: {0}")]
    AuthorizationFailed(String),
    
    #[error("无效的令牌: {0}")]
    InvalidToken(String),
    
    #[error("令牌已过期")]
    TokenExpired,
    
    #[error("权限不足: 需要 {required}, 当前 {current}")]
    InsufficientPermissions { required: String, current: String },
    
    #[error("未知用户: {0}")]
    UnknownUser(String),
    
    #[error("无效的凭据: {0}")]
    InvalidCredentials(String),
    
    #[error("账户已锁定: {0}")]
    AccountLocked(String),
    
    #[error("账户已禁用: {0}")]
    AccountDisabled(String),
    
    #[error("会话已过期")]
    SessionExpired,
    
    #[error("会话无效: {0}")]
    InvalidSession(String),
    
    #[error("多因素认证失败: {0}")]
    MfaFailed(String),
    
    #[error("密码策略违规: {0}")]
    PasswordPolicyViolation(String),
    
    #[error("访问频率过高: {0}")]
    RateLimitExceeded(String),
    
    #[error("IP地址被封禁: {0}")]
    IpBlocked(String),
    
    #[error("内部错误: {0}")]
    InternalError(String),
    
    #[error("配置错误: {0}")]
    ConfigurationError(String),
    
    #[error("网络错误: {0}")]
    NetworkError(String),
    
    #[error("加密错误: {0}")]
    CryptographicError(String),
    
    #[error("序列化错误: {0}")]
    SerializationError(String),
    
    #[error("不支持的操作: {0}")]
    UnsupportedOperation(String),
}

/// 安全通用错误类型
#[derive(Error, Debug, Clone, PartialEq)]
pub enum SecurityError {
    #[error("无效的凭据: {0}")]
    InvalidCredentials(String),
    
    #[error("权限被拒绝: {0}")]
    PermissionDenied(String),
    
    #[error("资源不存在: {0}")]
    ResourceNotFound(String),
    
    #[error("操作被禁止: {0}")]
    OperationForbidden(String),
    
    #[error("安全策略违规: {0}")]
    PolicyViolation(String),
    
    #[error("审计失败: {0}")]
    AuditFailed(String),
    
    #[error("加密失败: {0}")]
    EncryptionFailed(String),
    
    #[error("解密失败: {0}")]
    DecryptionFailed(String),
    
    #[error("签名验证失败: {0}")]
    SignatureVerificationFailed(String),
    
    #[error("证书验证失败: {0}")]
    CertificateVerificationFailed(String),
    
    #[error("密钥管理错误: {0}")]
    KeyManagementError(String),
    
    #[error("随机数生成失败: {0}")]
    RandomGenerationFailed(String),
    
    #[error("哈希计算失败: {0}")]
    HashComputationFailed(String),
    
    #[error("时间戳验证失败: {0}")]
    TimestampValidationFailed(String),
    
    #[error("数据完整性检查失败: {0}")]
    IntegrityCheckFailed(String),
    
    #[error("安全配置无效: {0}")]
    InvalidSecurityConfiguration(String),
    
    #[error("协议错误: {0}")]
    ProtocolError(String),
    
    #[error("编码错误: {0}")]
    EncodingError(String),
    
    #[error("解码错误: {0}")]
    DecodingError(String),
    
    #[error("验证失败: {0}")]
    ValidationFailed(String),
}

/// 认证结果类型
pub type AuthResult<T> = Result<T, AuthError>;

/// 安全结果类型
pub type SecurityResult<T> = Result<T, SecurityError>;

impl AuthError {
    /// 检查是否为临时错误（可重试）
    pub fn is_temporary(&self) -> bool {
        matches!(
            self,
            AuthError::NetworkError(_) |
            AuthError::InternalError(_) |
            AuthError::SessionExpired |
            AuthError::RateLimitExceeded(_)
        )
    }

    /// 检查是否为认证相关错误
    pub fn is_authentication_error(&self) -> bool {
        matches!(
            self,
            AuthError::AuthenticationFailed(_) |
            AuthError::InvalidCredentials(_) |
            AuthError::InvalidToken(_) |
            AuthError::TokenExpired |
            AuthError::UnknownUser(_) |
            AuthError::AccountLocked(_) |
            AuthError::AccountDisabled(_) |
            AuthError::MfaFailed(_)
        )
    }

    /// 检查是否为授权相关错误
    pub fn is_authorization_error(&self) -> bool {
        matches!(
            self,
            AuthError::AuthorizationFailed(_) |
            AuthError::InsufficientPermissions { .. }
        )
    }

    /// 检查是否为会话相关错误
    pub fn is_session_error(&self) -> bool {
        matches!(
            self,
            AuthError::SessionExpired |
            AuthError::InvalidSession(_)
        )
    }

    /// 获取错误类别
    pub fn category(&self) -> &'static str {
        match self {
            AuthError::AuthenticationFailed(_) |
            AuthError::InvalidCredentials(_) |
            AuthError::InvalidToken(_) |
            AuthError::TokenExpired |
            AuthError::UnknownUser(_) |
            AuthError::AccountLocked(_) |
            AuthError::AccountDisabled(_) |
            AuthError::MfaFailed(_) => "authentication",
            
            AuthError::AuthorizationFailed(_) |
            AuthError::InsufficientPermissions { .. } => "authorization",
            
            AuthError::SessionExpired |
            AuthError::InvalidSession(_) => "session",
            
            AuthError::RateLimitExceeded(_) |
            AuthError::IpBlocked(_) => "rate_limiting",
            
            AuthError::PasswordPolicyViolation(_) => "policy",
            
            AuthError::NetworkError(_) => "network",
            
            AuthError::CryptographicError(_) => "cryptographic",
            
            AuthError::ConfigurationError(_) => "configuration",
            
            _ => "general",
        }
    }

    /// 获取HTTP状态码建议
    pub fn suggested_http_status(&self) -> u16 {
        match self {
            AuthError::AuthenticationFailed(_) |
            AuthError::InvalidCredentials(_) |
            AuthError::InvalidToken(_) |
            AuthError::TokenExpired |
            AuthError::UnknownUser(_) |
            AuthError::MfaFailed(_) => 401, // Unauthorized
            
            AuthError::AuthorizationFailed(_) |
            AuthError::InsufficientPermissions { .. } |
            AuthError::AccountLocked(_) |
            AuthError::AccountDisabled(_) => 403, // Forbidden
            
            AuthError::RateLimitExceeded(_) => 429, // Too Many Requests
            
            AuthError::PasswordPolicyViolation(_) |
            AuthError::InvalidSession(_) => 400, // Bad Request
            
            AuthError::InternalError(_) |
            AuthError::CryptographicError(_) |
            AuthError::NetworkError(_) => 500, // Internal Server Error
            
            AuthError::ConfigurationError(_) => 503, // Service Unavailable
            
            _ => 500,
        }
    }
}

impl SecurityError {
    /// 检查是否为临时错误（可重试）
    pub fn is_temporary(&self) -> bool {
        matches!(
            self,
            SecurityError::KeyManagementError(_) |
            SecurityError::RandomGenerationFailed(_)
        )
    }

    /// 检查是否为验证相关错误
    pub fn is_validation_error(&self) -> bool {
        matches!(
            self,
            SecurityError::SignatureVerificationFailed(_) |
            SecurityError::CertificateVerificationFailed(_) |
            SecurityError::TimestampValidationFailed(_) |
            SecurityError::IntegrityCheckFailed(_) |
            SecurityError::ValidationFailed(_)
        )
    }

    /// 检查是否为加密相关错误
    pub fn is_cryptographic_error(&self) -> bool {
        matches!(
            self,
            SecurityError::EncryptionFailed(_) |
            SecurityError::DecryptionFailed(_) |
            SecurityError::HashComputationFailed(_) |
            SecurityError::KeyManagementError(_) |
            SecurityError::RandomGenerationFailed(_)
        )
    }

    /// 获取错误类别
    pub fn category(&self) -> &'static str {
        match self {
            SecurityError::InvalidCredentials(_) |
            SecurityError::PermissionDenied(_) => "access_control",
            
            SecurityError::EncryptionFailed(_) |
            SecurityError::DecryptionFailed(_) |
            SecurityError::HashComputationFailed(_) |
            SecurityError::KeyManagementError(_) |
            SecurityError::RandomGenerationFailed(_) => "cryptographic",
            
            SecurityError::SignatureVerificationFailed(_) |
            SecurityError::CertificateVerificationFailed(_) |
            SecurityError::TimestampValidationFailed(_) |
            SecurityError::IntegrityCheckFailed(_) |
            SecurityError::ValidationFailed(_) => "validation",
            
            SecurityError::PolicyViolation(_) => "policy",
            
            SecurityError::AuditFailed(_) => "audit",
            
            SecurityError::ProtocolError(_) => "protocol",
            
            SecurityError::EncodingError(_) |
            SecurityError::DecodingError(_) => "encoding",
            
            _ => "general",
        }
    }
}

// 实现从常见错误类型的转换
impl From<std::io::Error> for AuthError {
    fn from(error: std::io::Error) -> Self {
        AuthError::NetworkError(error.to_string())
    }
}

impl From<serde_json::Error> for AuthError {
    fn from(error: serde_json::Error) -> Self {
        AuthError::SerializationError(error.to_string())
    }
}

impl From<std::io::Error> for SecurityError {
    fn from(error: std::io::Error) -> Self {
        SecurityError::ProtocolError(error.to_string())
    }
}

impl From<serde_json::Error> for SecurityError {
    fn from(error: serde_json::Error) -> Self {
        SecurityError::EncodingError(error.to_string())
    }
}

// 允许在 AuthError 和 SecurityError 之间转换
impl From<SecurityError> for AuthError {
    fn from(error: SecurityError) -> Self {
        match error {
            SecurityError::InvalidCredentials(msg) => AuthError::InvalidCredentials(msg),
            SecurityError::PermissionDenied(msg) => AuthError::AuthorizationFailed(msg),
            SecurityError::PolicyViolation(msg) => AuthError::PasswordPolicyViolation(msg),
            SecurityError::EncryptionFailed(msg) => AuthError::CryptographicError(msg),
            SecurityError::DecryptionFailed(msg) => AuthError::CryptographicError(msg),
            SecurityError::ValidationFailed(msg) => AuthError::InvalidCredentials(msg),
            _ => AuthError::InternalError(error.to_string()),
        }
    }
}

impl From<AuthError> for SecurityError {
    fn from(error: AuthError) -> Self {
        match error {
            AuthError::InvalidCredentials(msg) => SecurityError::InvalidCredentials(msg),
            AuthError::AuthorizationFailed(msg) => SecurityError::PermissionDenied(msg),
            AuthError::InsufficientPermissions { required, current: _ } => {
                SecurityError::PermissionDenied(format!("Missing permission: {}", required))
            }
            AuthError::PasswordPolicyViolation(msg) => SecurityError::PolicyViolation(msg),
            AuthError::CryptographicError(msg) => SecurityError::EncryptionFailed(msg),
            _ => SecurityError::ValidationFailed(error.to_string()),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_auth_error_categories() {
        assert_eq!(
            AuthError::AuthenticationFailed("test".to_string()).category(),
            "authentication"
        );
        
        assert_eq!(
            AuthError::AuthorizationFailed("test".to_string()).category(),
            "authorization"
        );
        
        assert_eq!(
            AuthError::SessionExpired.category(),
            "session"
        );
        
        assert_eq!(
            AuthError::RateLimitExceeded("test".to_string()).category(),
            "rate_limiting"
        );
    }

    #[test]
    fn test_auth_error_types() {
        let auth_error = AuthError::AuthenticationFailed("test".to_string());
        assert!(auth_error.is_authentication_error());
        assert!(!auth_error.is_authorization_error());
        assert!(!auth_error.is_session_error());
        
        let authz_error = AuthError::InsufficientPermissions {
            required: "admin".to_string(),
            current: "user".to_string(),
        };
        assert!(!authz_error.is_authentication_error());
        assert!(authz_error.is_authorization_error());
        assert!(!authz_error.is_session_error());
    }

    #[test]
    fn test_http_status_suggestions() {
        assert_eq!(
            AuthError::AuthenticationFailed("test".to_string()).suggested_http_status(),
            401
        );
        
        assert_eq!(
            AuthError::AuthorizationFailed("test".to_string()).suggested_http_status(),
            403
        );
        
        assert_eq!(
            AuthError::RateLimitExceeded("test".to_string()).suggested_http_status(),
            429
        );
        
        assert_eq!(
            AuthError::InternalError("test".to_string()).suggested_http_status(),
            500
        );
    }

    #[test]
    fn test_security_error_categories() {
        assert_eq!(
            SecurityError::EncryptionFailed("test".to_string()).category(),
            "cryptographic"
        );
        
        assert_eq!(
            SecurityError::SignatureVerificationFailed("test".to_string()).category(),
            "validation"
        );
        
        assert_eq!(
            SecurityError::PolicyViolation("test".to_string()).category(),
            "policy"
        );
    }

    #[test]
    fn test_error_conversion() {
        let security_error = SecurityError::InvalidCredentials("bad password".to_string());
        let auth_error: AuthError = security_error.into();
        assert!(matches!(auth_error, AuthError::InvalidCredentials(_)));
        
        let auth_error = AuthError::AuthorizationFailed("access denied".to_string());
        let security_error: SecurityError = auth_error.into();
        assert!(matches!(security_error, SecurityError::PermissionDenied(_)));
    }

    #[test]
    fn test_temporary_errors() {
        assert!(AuthError::NetworkError("connection failed".to_string()).is_temporary());
        assert!(AuthError::RateLimitExceeded("too many requests".to_string()).is_temporary());
        assert!(!AuthError::InvalidCredentials("bad password".to_string()).is_temporary());
        
        assert!(SecurityError::KeyManagementError("key rotation failed".to_string()).is_temporary());
        assert!(!SecurityError::PolicyViolation("policy violated".to_string()).is_temporary());
    }
}